﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using IQToolkit.Data;
using System.Data.Common;
using IQToolkit.Data.Common;
using System.Reflection;
using IQToolkit.Data.SqlClient;
using System.Data.SqlClient;
using IQToolkit;
using System.Data.SqlTypes;

namespace Jmr.Entity.Poco
{
	public class JmrEntityProvider : DbEntityProvider
	{
		public JmrEntityProvider(Type entityType, string connectionString, DatabaseMapper dbMap)
			: base(new SqlConnection(connectionString), new JmrDatabaseMapping(new TSqlLanguage(), dbMap, entityType), QueryPolicy.Default)
		{

		}

		public override object Convert(object value, Type type)
		{
			Type vtype = value.GetType();
			if (vtype == typeof(System.Byte[]))
			{
				type = TypeHelper.GetNonNullableType(type);
				if (type == typeof(System.Int32) ||
					type == typeof(System.UInt32))
				{
					int rowVersion =(int)Math.Abs((BitConverter.ToInt64((byte[])value, 0) / Math.Pow(10, 13)));
					return rowVersion;
				}
			}
			return base.Convert(value, type);
		}

		public static DbEntityProvider FromSqlProvider(Type entityType, string connectionString, DatabaseMapper dbMap)
		{
			Type providerType = typeof(SqlQueryProvider);
			if (providerType == null)
				throw new InvalidOperationException(string.Format("Unable to find query sessionProvider '{0}'", "IQToolkit.Data.SqlClient"));

			Type adoConnectionType = typeof(SqlConnection);
			if (adoConnectionType == null)
				throw new InvalidOperationException(string.Format("Unable to deduce ADO sessionProvider for '{0}'", providerType.Name));
			DbConnection connection = (DbConnection)Activator.CreateInstance(adoConnectionType);

			// is the connection string just a filename?
			if (!connectionString.Contains('='))
			{
				MethodInfo gcs = providerType.GetMethod("GetConnectionString", BindingFlags.Static | BindingFlags.Public, null, new Type[] { typeof(string) }, null);
				if (gcs != null)
				{
					connectionString = (string)gcs.Invoke(null, new object[] { connectionString });
				}
			}

			connection.ConnectionString = connectionString;

			Type languageType = typeof(TSqlLanguage);
			if (languageType == null)
				throw new InvalidOperationException(string.Format("Unabled to determine correct QueryLanguage for '{0}'", providerType.Name));
			var language = (QueryLanguage)Activator.CreateInstance(languageType);
			var mapping = new JmrDatabaseMapping(language, dbMap, entityType);

			return (DbEntityProvider)Activator.CreateInstance(providerType, new object[] { connection, mapping, QueryPolicy.Default });
		}

		public static DbEntityProvider FromSqlProvider<TEntity>(string connectionString, DatabaseMapper dbMap)
		{
			return FromSqlProvider(typeof(TEntity), connectionString, dbMap);
		}

	}
}
